package com.kwdb.sdk.data;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 数据点类 - 支持Telegraf Line Protocol格式
 * 
 * 支持的数据类型：
 * - String: 字符串类型
 * - Integer: 整数类型  
 * - Long: 长整数类型
 * - Double: 双精度浮点类型
 * - Boolean: 布尔类型
 */
public class DataPoint {
    
    private String measurement;
    private Map<String, String> tags;
    private Map<String, Object> fields;
    private long timestamp;
    private TimeUnit timeUnit;
    
    public DataPoint(String measurement) {
        this.measurement = measurement;
        this.tags = new HashMap<>();
        this.fields = new HashMap<>();
        this.timestamp = System.currentTimeMillis();
        this.timeUnit = TimeUnit.MILLISECONDS;
    }
    
    public DataPoint(String measurement, long timestamp) {
        this(measurement);
        this.timestamp = timestamp;
    }
    
    public DataPoint(String measurement, long timestamp, TimeUnit timeUnit) {
        this(measurement, timestamp);
        this.timeUnit = timeUnit;
    }
    
    /**
     * 添加标签
     * @param key 标签键
     * @param value 标签值
     * @return DataPoint
     */
    public DataPoint addTag(String key, String value) {
        tags.put(key, value);
        return this;
    }
    
    /**
     * 添加字段 - 字符串类型
     * @param key 字段键
     * @param value 字段值
     * @return DataPoint
     */
    public DataPoint addField(String key, String value) {
        fields.put(key, value);
        return this;
    }
    
    /**
     * 添加字段 - 整数类型
     * @param key 字段键
     * @param value 字段值
     * @return DataPoint
     */
    public DataPoint addField(String key, int value) {
        fields.put(key, value);
        return this;
    }
    
    /**
     * 添加字段 - 长整数类型
     * @param key 字段键
     * @param value 字段值
     * @return DataPoint
     */
    public DataPoint addField(String key, long value) {
        fields.put(key, value);
        return this;
    }
    
    /**
     * 添加字段 - 双精度浮点类型
     * @param key 字段键
     * @param value 字段值
     * @return DataPoint
     */
    public DataPoint addField(String key, double value) {
        fields.put(key, value);
        return this;
    }
    
    /**
     * 添加字段 - 布尔类型
     * @param key 字段键
     * @param value 字段值
     * @return DataPoint
     */
    public DataPoint addField(String key, boolean value) {
        fields.put(key, value);
        return this;
    }
    
    /**
     * 设置时间戳
     * @param timestamp 时间戳
     * @return DataPoint
     */
    public DataPoint setTimestamp(long timestamp) {
        this.timestamp = timestamp;
        return this;
    }
    
    /**
     * 设置时间单位
     * @param timeUnit 时间单位
     * @return DataPoint
     */
    public DataPoint setTimeUnit(TimeUnit timeUnit) {
        this.timeUnit = timeUnit;
        return this;
    }
    
    /**
     * 转换为Telegraf Line Protocol格式
     * @return Line Protocol字符串
     */
    public String toLineProtocol() {
        StringBuilder sb = new StringBuilder();
        
        // 添加measurement
        sb.append(escapeMeasurement(measurement));
        
        // 添加tags
        if (!tags.isEmpty()) {
            sb.append(",");
            boolean first = true;
            for (Map.Entry<String, String> entry : tags.entrySet()) {
                if (!first) {
                    sb.append(",");
                }
                sb.append(escapeTag(entry.getKey())).append("=").append(escapeTag(entry.getValue()));
                first = false;
            }
        }
        
        // 添加fields
        sb.append(" ");
        boolean first = true;
        for (Map.Entry<String, Object> entry : fields.entrySet()) {
            if (!first) {
                sb.append(",");
            }
            sb.append(escapeField(entry.getKey())).append("=").append(formatFieldValue(entry.getValue()));
            first = false;
        }
        
        // 添加时间戳
        sb.append(" ").append(timestamp);
        
        return sb.toString();
    }
    
    private String escapeMeasurement(String measurement) {
        return measurement.replaceAll("([, ])", "\\\\$1");
    }
    
    private String escapeTag(String tag) {
        return tag.replaceAll("([,= ])", "\\\\$1");
    }
    
    private String escapeField(String field) {
        return field.replaceAll("([,= ])", "\\\\$1");
    }
    
    private String formatFieldValue(Object value) {
        if (value instanceof String) {
            return "\"" + ((String) value).replaceAll("\"", "\\\\\"") + "\"";
        } else if (value instanceof Number) {
            return value.toString();
        } else if (value instanceof Boolean) {
            return value.toString();
        } else {
            return "\"" + value.toString().replaceAll("\"", "\\\\\"") + "\"";
        }
    }
    
    // Getters
    public String getMeasurement() {
        return measurement;
    }
    
    public Map<String, String> getTags() {
        return tags;
    }
    
    public Map<String, Object> getFields() {
        return fields;
    }
    
    public long getTimestamp() {
        return timestamp;
    }
    
    public TimeUnit getTimeUnit() {
        return timeUnit;
    }
    
    @Override
    public String toString() {
        return toLineProtocol();
    }
}
